package com.https;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.zip.GZIPInputStream;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.Header;
import org.apache.http.HeaderIterator;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.params.ConnRoutePNames;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HTTP;
import org.apache.log4j.Logger;

import com.google.common.collect.Multimap;
import com.utilities.Bundle;
import com.utilities.StringHelper;

/**
 * 
 * http request Core API 
 * 
 */
/**
* @ClassName: HttpCore
* @Description: TODO
* @author alterhu2020@gmail.com
* @date Feb 15, 2014 9:28:20 PM
* 
*/

public class HttpCore {
	/************** log object **************/
	private static final Logger logger = Logger.getLogger(HttpCore.class);

	public String JSESSIONID;
	public String BIGipServerotn;

	public HttpCore() {

	}

	public HttpCore(String JSESSIONID, String BIGipServerotn) {
		this.JSESSIONID = JSESSIONID;
		this.BIGipServerotn = BIGipServerotn;
	}

	private static X509TrustManager tm = new X509TrustManager() {
		public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException {
		}

		public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException {
		}

		public X509Certificate[] getAcceptedIssuers() {
			return null;
		}
	};

	/**
	 * init HttpClient object  if it's https ,download the cert automatically
	 * 
	 * @return
	 * @throws KeyManagementException
	 * @throws NoSuchAlgorithmException
	 */
	public static HttpClient getHttpClient(boolean ishttps) throws KeyManagementException, NoSuchAlgorithmException {
		
		HttpClient httpclient=null;
		if(ishttps){
		SSLContext sslcontext = SSLContext.getInstance("TLS");
		sslcontext.init(null, new TrustManager[] { tm }, null);
		/*
		 * 20140123 Alter；add the comment
		 */
		SSLSocketFactory ssf = new SSLSocketFactory(sslcontext,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
		ClientConnectionManager ccm = new DefaultHttpClient().getConnectionManager();
		SchemeRegistry sr = ccm.getSchemeRegistry();
		sr.register(new Scheme("https", 443, ssf));
		HttpParams params = new BasicHttpParams();
		params.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 200000);
		params.setParameter(CoreConnectionPNames.SO_TIMEOUT, 200000);
		
		httpclient= new DefaultHttpClient(ccm, params);
		}else{
		     httpclient = new DefaultHttpClient();
		}
		
		String strtimeout=Bundle.getAbsolutePathString("http.timeout");
		String proxyserver=Bundle.getAbsolutePathString("proxy.ip");
		String proxyport=Bundle.getAbsolutePathString("proxy.port");
		if(strtimeout!=null&&(!strtimeout.equals(""))){
			int timeout=Integer.parseInt(strtimeout);
			HttpParams params = httpclient.getParams();
			HttpConnectionParams.setConnectionTimeout(params, timeout);
			HttpConnectionParams.setSoTimeout(params,timeout);
		}
		if(proxyserver!=null&&(!proxyserver.equals(""))){
				int port=0;
				if(proxyport==null||proxyport.equals("")){
					port=80;
				}else{
					port=Integer.parseInt(proxyport);
				}
				
				HttpHost proxy = new HttpHost(proxyserver, port, "http");
			    httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
		}
		
	    
	    
		return httpclient;
	}

	/**
	 * print the request parameter
	 * 
	 * @param params
	 */
	public void printParams(List<NameValuePair> params) {
		// output the commit parameters
		String p = "";
		if(params==null){
			
		}else{
			
			for (NameValuePair n : params) {
				p += n.getName() + " => " + n.getValue() + " \n";
			}
		}
		logger.info("打印发送的request的参数是 : \n" + p);
	}

	/**
	 * print request header
	 * 
	 * @param headers
	 */
	public void printHeader(HeaderIterator headers) {
		HeaderIterator its = headers;
		int k=0;
		while (its.hasNext()) {			
			logger.info("打印发送的request的header[ "+k+"] 是: " + its.next());
			k=k+1;
		}
		logger.info("***********************************结束***************************************");
		logger.info("");
	}

	/**
	 * print response header
	 * 
	 * @param header
	 */
	public void printHeader(Header[] headers) {
		if(headers.length>0){
			for (int i = 0; i < headers.length; i++) {
				logger.info("响应返回的header[ " + headers[i].getName() + "] 是 ： " + headers[i].getValue());
			}
		}
		logger.info("***********************************结束***************************************");
		logger.info("");
	}

	/**
	 * create the post request
	 * 
	 * @param url
	 * @return HttpPost
	 */
	public HttpPost getHttpPost(String url, Map<String, String> cookieMap) {
		// create the post request
		HttpPost post = new HttpPost(url);
		if (!StringHelper.isEmptyString(JSESSIONID) && !StringHelper.isEmptyString(BIGipServerotn)) {
			if (cookieMap != null) {
				String cookieStr = "JSESSIONID=" + JSESSIONID;
				for (Map.Entry<String, String> entry : cookieMap.entrySet()) {
					cookieStr += "; " + entry.getKey() + "=" + entry.getValue();
				}
				cookieStr += "; BIGipServerotn=" + BIGipServerotn;
				logger.info("Post请求的最终网站的Cookies,Cookie: "+cookieStr);
				post.addHeader("Cookie", cookieStr);
			} else {
				// put it in session
				post.addHeader("Cookie", "JSESSIONID=" + JSESSIONID + ";BIGipServerotn=" + BIGipServerotn);
				logger.info("Post请求的初始化的Cookies,Cookie : "+"JSESSIONID=" + JSESSIONID + ";BIGipServerotn=" + BIGipServerotn);
			}
		}
		
		return post;
	}

	/**
	 * create the get request
	 * 
	 * @param url
	 * @return HttpGet
	 */
	public HttpGet getHttpGet(String url, Map<String, String> cookieMap) {
		// create the get request
		HttpGet get = new HttpGet(url);
		if (cookieMap != null) {
			String cookieStr = "JSESSIONID=" + JSESSIONID;
			for (Map.Entry<String, String> entry : cookieMap.entrySet()) {
				cookieStr += "; " + entry.getKey() + "=" + entry.getValue();
			}
			cookieStr += "; BIGipServerotn=" + BIGipServerotn;
			logger.info("get请求的最终网站的Cookies,Cookie: "+cookieStr);
			get.addHeader("Cookie", cookieStr);
		} else {
			// put it in session
			get.addHeader("Cookie", "JSESSIONID=" + JSESSIONID + ";BIGipServerotn=" + BIGipServerotn);
			logger.info("get请求的初始化的Cookies,Cookie : "+"JSESSIONID=" + JSESSIONID + ";BIGipServerotn=" + BIGipServerotn);
		}
		return get;
	}

	/**
	 * set the request header
	 * 
	 * @param headerMap
	 * @param get
	 */
	public void setHeader(Map<String, String> headerMap, HttpRequestBase request) {
		for (Map.Entry<String, String> c : headerMap.entrySet()) {
			request.setHeader(c.getKey(), c.getValue());
		}
		logger.info("需要设置请求的header是: "+headerMap.toString());
	}

	

	/**
	 * 
	 * 设set the parameters
	 * 
	 * @param params
	 * @return
	 */
	public List<NameValuePair> setParams(Multimap<String, String> dataMap) {
		// the data form
		List <NameValuePair> nvps=null;
		if(dataMap != null && dataMap.size() > 0){
			logger.info("需要发送请求的参数值为: "+dataMap.toString());
			 nvps= new ArrayList <NameValuePair>();
			for(String key: dataMap.keySet()){
				Collection<String> indexkey=dataMap.get(key);
				if(indexkey!=null){
					for (Iterator<String> iterator = indexkey.iterator(); iterator.hasNext();){
						String value=iterator.next();
					    nvps.add(new BasicNameValuePair(key,value ));
					 }
				}else{
					 nvps.add(new BasicNameValuePair(key,""));
				}
	           
			}
		}
		return nvps;
	}

	public String getRequest(String url, Multimap<String, String> params, Map<String, String> headerMap, Map<String, String> cookieMap) throws KeyManagementException,
			NoSuchAlgorithmException {
		logger.info("-------------------开始发送一个get 的请求-------------------");
		
		// get the parameters
		List<NameValuePair> parameters = setParams(params);
		// out put the parameters
		printParams(parameters);
		@SuppressWarnings("deprecation")
		String urlString = URLEncodedUtils.format(parameters, HTTP.UTF_8);
		logger.info("Get发送的完整url 是：  " + url + "?" + urlString);
		
		HttpGet get = getHttpGet(url + "?" + urlString, cookieMap);
		//frame.logger("请求一个URL:"+url+"?"+urlString);
		// set  the request header
		setHeader(headerMap, get);
		// print headerMap
		printHeader(get.headerIterator());
		
		HttpClient httpclient=null;
		if(get.getRequestLine().getUri().toLowerCase().startsWith("https")){
			httpclient= getHttpClient(true);
		}else{
		    httpclient = getHttpClient(false);
		}
				
		String responseBody =null;
		try {
				HttpResponse response = httpclient.execute(get);
				responseBody=getReponseContent(response.getEntity());
				//print headerMap
				printHeader(response.getAllHeaders());
			
		} catch (Exception e) {
			logger.error("发送request遇到异常情况，错误 : ", e);
		} finally {
			httpclient.getConnectionManager().shutdown();
		}
		logger.info("发送的request返回的数据字符串为： : \n" + responseBody);
		logger.info("-------------------发送 get request结束-------------------");
		
		return responseBody;
	}
	

	
	public void getCookie(String url, Map<String, String> headerMap, Map<String, String> cookieMap) throws KeyManagementException, NoSuchAlgorithmException {
		logger.info("-------------------得到网站的初始化cookies值-------------------");
		//HttpClient httpclient = getHttpClient();
		HttpGet get = getHttpGet(url, cookieMap);
		
		
		HttpClient httpclient=null;
		if(get.getRequestLine().getUri().toLowerCase().startsWith("https")){
			httpclient= getHttpClient(true);
		}else{
		    httpclient = getHttpClient(false);
		}
		
		// set the header
		setHeader(headerMap, get);
		// print headerMap
		printHeader(get.headerIterator());
		try {
			HttpResponse response = httpclient.execute(get);
			printHeader(response.getAllHeaders());
			// get the header
			Header[] headers = response.getHeaders("Set-Cookie");
			for (int i = 0; i < headers.length; i++) {
				
					String cookie = headers[i].getValue();
					String cookieName = cookie.split("=")[0];
					String cookieValue = cookie.split("=")[1].split(";")[0];
					if (cookieName.equals("JSESSIONID")) {
						this.JSESSIONID = cookieValue;
					}
					if (cookieName.equals("BIGipServerotn")) {
						this.BIGipServerotn = cookieValue;
					}				
			}
			//frame.logger("return msg : \n" + responseBody);
		logger.info("得到cookies已经获得了相关的初始值,jessionid = " + JSESSIONID + ";bigipserverotn = " + BIGipServerotn);
		} catch (Exception e) {
		    logger.error(e.toString());
		} finally {
			httpclient.getConnectionManager().shutdown();
		}
		logger.info("-------------------获取网站初始化的cookies的request结束-------------------");
	}

	/**
	 * 
	 * get the pass code
	 * 
	 * @param url
	 * @param path
	 * @param headerMap
	 * @throws KeyManagementException
	 * @throws NoSuchAlgorithmException
	 */
	@SuppressWarnings("unused")
	public void getPassCode(String url,String path, Map<String, String> headerMap, Map<String, String> cookieMap) throws KeyManagementException, NoSuchAlgorithmException {
		InputStream instream=null;
		logger.info("-------------------获取验证码开始-------------------");
		//HttpClient httpclient = getHttpClient();
		HttpGet get = getHttpGet(url, cookieMap);
		
		HttpClient httpclient=null;
		if(get.getRequestLine().getUri().toLowerCase().startsWith("https")){
			httpclient= getHttpClient(true);
		}else{
		    httpclient = getHttpClient(false);
		}
		
		
		if (url.contains("login")) {
			// set the header
			setHeader(headerMap, get);
			// print headerMap
			printHeader(get.headerIterator());
		} else {
			// set the request header
			setHeader(headerMap, get);
			// print headerMap
			printHeader(get.headerIterator());
		}
		try {
			HttpResponse response = httpclient.execute(get);
			// print headerMap
			printHeader(response.getAllHeaders());
			HttpEntity entity = response.getEntity();
			if (entity != null) {
				instream = entity.getContent();
				File savedfile=new File(path);
				if(savedfile.exists()){
					savedfile.delete();
				}
				OutputStream out = new FileOutputStream(new File(path));
				int byteread = 0;
				byte[] tmp = new byte[1];
				while ((byteread = instream.read(tmp)) != -1) {
					out.write(tmp);
				}
				out.flush();
				out.close();
				
				
			}
		} catch (Exception e) {
		//	frame.logger("getPassCode error : "+e);
			System.out.println("获取验证码遇到异常，错误是:"+e.getMessage());
		} finally {
			httpclient.getConnectionManager().shutdown();
			
		}
		
		logger.info("-----------------获取验证码请求结束-------------------");
		//return instream;
	}

	/**
	 * 
	 * public post
	 * 
	 * @param url
	 * @param params
	 * @param headerMap
	 * @return
	 * @throws KeyManagementException
	 * @throws NoSuchAlgorithmException
	 */
	public String postRequest(String url, Multimap<String, String> params, Map<String, String> headerMap, Map<String, String> cookieMap) throws KeyManagementException,
			NoSuchAlgorithmException {
		logger.info("-------------------发送一个post的request开始-------------------");
	//	HttpClient httpclient = getHttpClient();
		HttpPost post = getHttpPost(url, cookieMap);
		
		
		HttpClient httpclient=null;
		if(post.getRequestLine().getUri().toLowerCase().startsWith("https")){
			httpclient= getHttpClient(true);
		}else{
		    httpclient = getHttpClient(false);
		}
		
		// header
		setHeader(headerMap, post);
		// print header Map
		printHeader(post.headerIterator());
		// get the parameters
		List<NameValuePair> parameters = setParams(params);
		// output the parameters
		printParams(parameters);
		String responseBody = null;
		try {
			if(parameters!=null){
			@SuppressWarnings("deprecation")
			UrlEncodedFormEntity uef = new UrlEncodedFormEntity(parameters, HTTP.UTF_8);
			post.setEntity(uef);
			@SuppressWarnings("deprecation")
			String posturl=url + "?" + URLEncodedUtils.format(parameters, HTTP.UTF_8);
			logger.info("Post的完整URL 是： "+posturl);
			//frame.logger("请求的URL 是: "+posturl);
			}
			HttpResponse response = httpclient.execute(post);
			// print cookie
			printHeader(response.getAllHeaders());
			responseBody=getReponseContent(response.getEntity());
			logger.info("Post的request的返回字符串数据是 : \n" + responseBody);
			//frame.logger("返回的请求字符串为："+responseBody);
		} catch (Exception e) {
			logger.error("发送request遇到异常:", e);
		} finally {
			httpclient.getConnectionManager().shutdown();
		}
		logger.info("-------------------发送一个post的requst请求结束-------------------");
		return responseBody;
	}

    /*
     * 得到返回的数据流	
     */
	private static String getReponseContent(HttpEntity entities) throws IOException {
		  InputStream input=null;
		  Header encoding = entities.getContentEncoding(); 
		  if (encoding != null) {
			     if (encoding.getValue().equals("gzip") || encoding.getValue().equals("zip") ||encoding.getValue().equals("application/x-gzip-compressed")) {
			    	 input= new GZIPInputStream(entities.getContent());
			     }else{
			    	 input=entities.getContent();
			     }
		  }else{
			  if(entities.getContentType()!=null){
				  input=entities.getContent();
			  }else{
				  logger.info("返回的数据流的getContentEncoding为空");
				  return null;
			  }
		  }
		  
		  BufferedReader in = new BufferedReader(new InputStreamReader(input,"UTF-8"));
		  StringBuffer buffer = new StringBuffer();
		  String line;
		  while ((line = in.readLine()) != null)
				buffer.append(line + "\n");
		  input.close();
		  
		 return buffer.toString();
	}
	
}